package main

import (
	"fmt"
	"github.com/casbin/casbin/v2"
	"log"
)

// checkPermission 权限检查函数
// 功能：验证指定用户对特定资源是否有操作权限，包含错误处理
// 参数：
//   - e: Casbin执行器实例
//   - user: 用户名
//   - resource: 资源路径
//   - action: 操作类型
func checkPermission(e *casbin.Enforcer, user, resource, action string) {
	// 执行权限检查，返回权限结果和可能的错误
	ok, err := e.Enforce(user, resource, action)
	if err != nil {
		// 权限检查过程中发生错误，记录错误信息
		log.Printf("权限检查出错: %v\n", err)
		return
	}

	// 根据权限检查结果输出可视化信息
	if ok {
		fmt.Printf("✅ %s 有权限 %s %s\n", user, action, resource)
	} else {
		fmt.Printf("❌ %s 无权限 %s %s\n", user, action, resource)
	}
}

// checkRole 角色检查函数
// 功能：验证指定用户是否拥有特定角色，包含错误处理
// 参数：
//   - e: Casbin执行器实例
//   - user: 用户名
//   - role: 角色名称
func checkRole(e *casbin.Enforcer, user, role string) {
	// 检查用户是否拥有指定角色
	hasRole, err := e.HasRoleForUser(user, role)
	if err != nil {
		// 角色检查过程中发生错误，记录错误信息
		log.Printf("角色检查出错: %v\n", err)
		return
	}

	// 根据角色检查结果输出可视化信息
	if hasRole {
		fmt.Printf("✅ %s 拥有角色: %s\n", user, role)
	} else {
		fmt.Printf("❌ %s 不拥有角色: %s\n", user, role)
	}
}

// main 程序主入口
// 功能：演示Casbin RBAC（基于角色的访问控制）完整功能
func main() {
	fmt.Println("=== Casbin RBAC 示例 ===")

	// 初始化基础Casbin执行器（ACL模式）
	// 使用基础模型文件和策略文件
	e, err := casbin.NewEnforcer("model.pml", "policy.csv")
	if err != nil {
		log.Fatalf("初始化 Casbin 失败: %v\n", err)
	}

	// 1. 基础权限检查（ACL模式）
	fmt.Println("\n--- 基础权限检查 ---")
	checkPermission(e, "zhangsan", "/index", "GET")  // 检查张三对/index的GET权限
	checkPermission(e, "zhangsan", "/users", "POST") // 检查张三对/users的POST权限
	checkPermission(e, "wangwu", "/users", "POST")   // 检查王五对/users的POST权限

	// 2. RBAC模式测试
	fmt.Println("\n=== 使用 RBAC 模式 ===")
	// 初始化RBAC专用的Casbin执行器
	// 使用RBAC模型文件和策略文件
	eRbac, err := casbin.NewEnforcer("rbac_model.conf", "rbac_policy.csv")
	if err != nil {
		// RBAC模式初始化失败，跳过RBAC相关测试
		log.Printf("RBAC模式初始化失败: %v，跳过RBAC示例\n", err)
	} else {
		// RBAC模式下的权限检查
		fmt.Println("\n--- RBAC模式权限检查 ---")
		checkPermission(eRbac, "zhangsan", "/admin", "POST") // admin角色应有/admin的POST权限
		checkPermission(eRbac, "wangwu", "/profile", "GET")  // user角色应有/profile的GET权限
		checkPermission(eRbac, "wangwu", "/admin", "GET")    // user角色不应有/admin的GET权限
		checkPermission(eRbac, "lisi", "/public", "GET")     // guest角色应有/public的GET权限
		checkPermission(eRbac, "lisi", "/profile", "GET")    // guest角色不应有/profile的GET权限

		// 角色检查功能演示
		fmt.Println("\n--- RBAC角色检查 ---")
		checkRole(eRbac, "zhangsan", "admin") // 检查张三是否拥有admin角色
		checkRole(eRbac, "wangwu", "user")    // 检查王五是否拥有user角色
		checkRole(eRbac, "lisi", "guest")     // 检查李四是否拥有guest角色

		// 动态角色管理演示
		fmt.Println("\n--- 动态管理角色 ---")
		// 为用户王五添加guest角色
		_, err = eRbac.AddRoleForUser("wangwu", "guest")
		if err == nil {
			fmt.Println("添加角色后:")
			// 验证角色添加是否成功
			checkRole(eRbac, "wangwu", "guest")
		}
	}

	// 3. 动态权限管理功能演示
	fmt.Println("\n--- 动态管理权限 ---")

	// 添加新权限演示
	fmt.Println("\n添加新权限:")
	_, err = e.AddPolicy("zhangsan", "/settings", "GET")
	if err != nil {
		log.Printf("添加权限失败: %v\n", err)
	} else {
		// 验证新添加的权限
		checkPermission(e, "zhangsan", "/settings", "GET")
	}

	// 删除权限演示
	fmt.Println("\n删除权限:")
	_, err = e.RemovePolicy("zhangsan", "/users", "POST")
	if err != nil {
		log.Printf("删除权限失败: %v\n", err)
	} else {
		// 验证权限删除效果
		checkPermission(e, "zhangsan", "/users", "POST")
	}

	// 4. 策略查看功能
	fmt.Println("\n--- 当前策略列表 ---")
	// 获取当前所有权限策略并显示
	policies := e.GetPolicy()
	for _, policy := range policies {
		fmt.Printf("  - %v\n", policy)
	}

	// 策略持久化提示（当前注释掉，避免频繁写入）
	// 要保存策略更改到文件，请取消下面的注释
	// err = e.SavePolicy()
	// if err != nil {
	// 	log.Printf("保存策略失败: %v\n", err)
	// }
}
